package cn.cloud.mqtt2redis.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class RedisService {

    @Value("${jedis.pool.database}")
    private String database;
    @Autowired
    private JedisPool JedisPool;
    @Autowired
    private MqttPublish mqttPublish;
    private Logger logger = LoggerFactory.getLogger(getClass());
    public static boolean isMachineIdToRedisCompleted = false;


    //从redis中读取所有设备列表
    public List<String> get_machineID_from_redis(){
        Jedis redisConn = JedisPool.getResource();
        redisConn.select(Integer.valueOf(database));
        List<String> machine_list = new ArrayList<>();
        if(redisConn.exists("MACHINE:ID_LIST")){
            machine_list = redisConn.lrange("MACHINE:ID_LIST",0,-1);
        }
        redisConn.close();
        return machine_list;
    }

    //从redis中读取有效deviceID
    public List<String> get_validMachineID_from_redis(){
        Jedis redisConn = JedisPool.getResource();
        redisConn.select(Integer.valueOf(database));
        List<String> machine_list = new ArrayList<>();
        if(redisConn.exists("MACHINE:REAL_ID_LIST")){
            machine_list = redisConn.lrange("MACHINE:REAL_ID_LIST", 0, -1);
        }
        redisConn.close();
        return machine_list;
    }

    //从redis中读取param_id
    public String get_paramID_from_redis(String machineID,String idType){
        Jedis redisConn = JedisPool.getResource();
        redisConn.select(Integer.valueOf(database));
        String paramID=null;
        switch (idType) {
            case "PROGID_MAP":
                paramID = redisConn.hget("PARAM:"+machineID+":CONTROLLER","VARIABLE#PROGID_MAP");
                break;
            case "FILE":
                paramID = redisConn.hget("PARAM:"+machineID+":CONTROLLER",idType);
                break;
        }
        //paramID = redisConn.hget("PARAM:"+machineID,idType);
        redisConn.close();
        return paramID;
    }

    //从redis中读取param，存入map
    public Map<String,String> get_paramMap_from_redis(String machineID){
        Jedis redisConn = JedisPool.getResource();
        redisConn.select(Integer.valueOf(database));
        Map<String,String> param_map = redisConn.hgetAll("PARAM:"+machineID);
        redisConn.close();
        return param_map;
    }

    //从redis中根据machineid和文件名称，获取对应的程序号
    public String get_progid_from_redis(String machineID,String prog_name){
        Jedis redisConn = JedisPool.getResource();
        redisConn.select(Integer.valueOf(database));
        if(!redisConn.exists("PROGMAP:"+machineID+":"+prog_name)){
            redisConn.close();
            return "";
        }
        String prog_id = redisConn.get("PROGMAP:"+machineID+":"+prog_name);
        redisConn.close();
        return prog_id;
    }

    //将设备发现的结果：设备列表，写入redis数据库
    public synchronized void set_machineID_to_redis_discovery(JSONArray machineList) {
        if(isMachineIdToRedisCompleted) return;      //设备发现消息筛选
        long startTime=System.currentTimeMillis();   //获取开始时间
        Jedis redisConn = JedisPool.getResource();
        redisConn.select(Integer.valueOf(database));
        //if(redisConn.exists("MACHINE:ID_LIST")) { redisConn.del("MACHINE:ID_LIST"); }
        //if(redisConn.exists("MACHINE:REAL_ID_LIST")) { redisConn.del("MACHINE:REAL_ID_LIST"); }
        for (int i=0;i<machineList.size();i++) {
            if(!redisConn.lrange("MACHINE:ID_LIST",0,-1).contains(machineList.getString(i))) {
                redisConn.rpush("MACHINE:ID_LIST", machineList.getString(i));
            }
        }
        redisConn.close();
        isMachineIdToRedisCompleted = true;
        long endTime=System.currentTimeMillis();   //获取结束时间
        logger.info("设备ID列表录入耗时: "+ (endTime-startTime) + "ms");
    }

    //设备注册DEVICEID写入
    public synchronized void set_machineID_to_redis_register(JSONArray machineList) {
        Jedis redisConn = JedisPool.getResource();
        redisConn.select(Integer.valueOf(database));
        for(int i=0;i<machineList.size();i++) {
            if(!redisConn.lrange("MACHINE:ID_LIST",0,-1).contains(machineList.getString(i))){
                redisConn.rpush("MACHINE:ID_LIST",machineList.getString(i));
                mqttPublish.publish_single_device_probe(machineList.getString(i));
            }
        }
        redisConn.close();
    }

    //有效machine列表,除去无效probe文件的设备
    public synchronized void set_realMachineID_to_redis(String machineID){
        Jedis redisConn = JedisPool.getResource();
        redisConn.select(Integer.valueOf(database));
        if(!redisConn.exists("MACHINE:REAL_ID_LIST")) {
            redisConn.rpush("MACHINE:REAL_ID_LIST", machineID);
        }else {
            if(!(redisConn.lrange("MACHINE:REAL_ID_LIST",0,-1).contains(machineID))){
                redisConn.rpush("MACHINE:REAL_ID_LIST",machineID);
                logger.info("valid_machine_list flush!");
            }
        }
        redisConn.close();
    }

    //写入params_id
    public synchronized void set_progid_to_redis(String machineID, Map<String, String> map) {
        Jedis redisConn = JedisPool.getResource();
        redisConn.select(Integer.valueOf(database));
        String key = "PARAM:"+ machineID;
        //hash写入
        if(redisConn.exists(key)) redisConn.del(key);
        redisConn.hmset(key, map);
        redisConn.close();
    }

    //G代码映射
    public synchronized void set_mapdata_to_redis(String machineID, Map<String, String> prog_map) {
        Jedis redisConn = JedisPool.getResource();
        redisConn.select(Integer.valueOf(database));
        for(Map.Entry<String, String> vo : prog_map.entrySet()) {
            String tmp[] = vo.getValue().split("/");
            String key = tmp[tmp.length - 1];
            String value = vo.getKey();
            redisConn.set("PROGMAP:" + machineID + ":" + key, value);
        }
        redisConn.close();
    }

    public void set_SampleChannel_ids_to_redis(String machineID, JSONArray ids) {
        Jedis redisConn = JedisPool.getResource();
        redisConn.select(Integer.valueOf(database));
        if(redisConn.exists("SAMPLECHANNEL:"+machineID)) redisConn.del("SAMPLECHANNEL:"+machineID);
        for(int index=0;index<ids.size();index++){
            redisConn.rpush("SAMPLECHANNEL:"+machineID,ids.getJSONObject(index).getString("id"));
        }
        redisConn.close();
    }

    public void set_version_to_redis(String machineID, String version){
        Jedis redisConn = JedisPool.getResource();
        redisConn.select(Integer.valueOf(database));
        redisConn.set("PARAM:"+ machineID+":VERSION",version);
        redisConn.close();
    }

    public void set_dataItem_id_to_redis(String machineID, Map<String, String> linkedHashMap) {
        Jedis redisConn = JedisPool.getResource();
        redisConn.select(Integer.valueOf(database));
        String key = "PARAM:"+ machineID+":DATAITEM";
        if(redisConn.exists(key)) redisConn.del(key);
        redisConn.hmset(key,linkedHashMap);
        redisConn.close();
    }

    public void set_component_controller_to_redis(String machineID, Map<String, String> linkedHashMap) {
        Jedis redisConn = JedisPool.getResource();
        redisConn.select(Integer.valueOf(database));
        String key = "PARAM:"+ machineID+":CONTROLLER";
        if(redisConn.exists(key)) redisConn.del(key);
        redisConn.hmset(key,linkedHashMap);
        redisConn.close();
    }

    public void set_component_axit_to_redis(String machineID, Map<String, String> linkedHashMap) {
        Jedis redisConn = JedisPool.getResource();
        redisConn.select(Integer.valueOf(database));
        String key = "PARAM:"+ machineID+":AXIS";
        //if(redisConn.exists(key)) redisConn.del(key);
        redisConn.hmset(key,linkedHashMap);
        redisConn.close();
    }
}
